﻿using HandyControl.Data;
using Newtonsoft.Json;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using TransformerManager.Shared.Dto.OperationLog;
using TransformerManager.Shared.Helper.HttpParams;
using TransformerManager.WPF.Common.Http.Service;
using hc = HandyControl.Controls;

namespace TransformerManager.WPF.OperationLogModule.ViewModels
{
    public class OperationLogViewModel : BindableBase, INavigationAware
    {
        private readonly IOperationLogService _operationLogService;

        public OperationLogViewModel(IOperationLogService operationLogService)
        {
            _operationLogService = operationLogService;

            InitCmd();
        }


        #region Command
        public DelegateCommand<FrameworkElement> RequestBodyCmd { private set; get; }

        public DelegateCommand SearchCmd { private set; get; }

        public DelegateCommand<FunctionEventArgs<int>> PageUpdatedCmd { private set; get; }

        #endregion


        #region 方法的定义

        private ObservableCollection<OperationLogsDto> _showOpLogsList
            = new ObservableCollection<OperationLogsDto>();
        public ObservableCollection<OperationLogsDto> ShowOpLogsList
        {
            set
            {
                _showOpLogsList = value;

                RaisePropertyChanged();
            }
            get
            {
                return _showOpLogsList;
            }
        }

        private OperationLogsDto _selectedOpLog
            = new OperationLogsDto();
        public OperationLogsDto SelectedOpLog
        {
            set
            {
                _selectedOpLog = value;

                RaisePropertyChanged();
            }
            get
            {
                return _selectedOpLog;
            }
        }

        private Visibility _isShowPaginationAndDataGrid
                = Visibility.Collapsed;
        public Visibility IsShowPaginationAndDataGrid
        {
            set
            {
                _isShowPaginationAndDataGrid = value;

                RaisePropertyChanged();
            }

            get
            {
                return _isShowPaginationAndDataGrid;
            }
        }

        private int _pageIndex = 1;
        public int PageIndex
        {
            set
            {
                _pageIndex = value;

                RaisePropertyChanged();
            }
            get
            {
                return _pageIndex;
            }
        }

        private int _maxPageCount;
        public int MaxPageCount
        {
            set
            {
                _maxPageCount = value;

                RaisePropertyChanged();
            }
            get
            {
                return _maxPageCount;
            }
        }

        private int _dataCountPerPage = 30;
        public int DataCountPerPage
        {
            set
            {
                _dataCountPerPage = value;

                RaisePropertyChanged();
            }

            get
            {
                return _dataCountPerPage;
            }
        }

        private string _userName= string.Empty;
        public string UserName
        {
            set
            {
                _userName = value;

                RaisePropertyChanged();
            }

            get
            {
                return _userName;
            }
        }

        private DateTime _from = DateTime.Today.AddDays(-15);
        public DateTime From
        {
            set
            {
                _from = value;

                RaisePropertyChanged();
            }
            get
            {
                return _from;
            }
        }

        private DateTime _end = DateTime.Today.AddHours(12);
        public DateTime End
        {
            set
            {
                _end = value;

                RaisePropertyChanged();
            }
            get
            {
                return _end;
            }
        }

        #endregion


        #region 函数的定义

        private void InitCmd()
        {
            RequestBodyCmd = new DelegateCommand<FrameworkElement>(async (FrameworkElement element) =>
            {
                await RetrieveRequestBodyContent(SelectedOpLog);
            });

            SearchCmd = new DelegateCommand(async () =>
            {
                await RetrieveDataGridSource(UserName, From, End, PageIndex, DataCountPerPage);
            });

            PageUpdatedCmd = new DelegateCommand<FunctionEventArgs<int>>(async (curPageNum) =>
            {
                await PageUpdated(curPageNum);
            });
        }

        public async Task RetrieveDataGridSource(
            string userName,
            DateTime operateTimeStart,
            DateTime operateTimeEnd,
            int pageIndex,
            int pageSize)
        {
            var resultWithHeaders = await _operationLogService.GetOperationLogsAsync(userName, operateTimeStart, operateTimeEnd, pageIndex, pageSize);
            
            if (resultWithHeaders == null || resultWithHeaders.Data.Count == 0)
            {
                ShowOpLogsList.Clear();
                IsShowPaginationAndDataGrid = 
                    _showOpLogsList.Count() == 0 ? Visibility.Collapsed : Visibility.Visible;
                return;
            }

            // 从响应中获取分页信息
            var headersParams = resultWithHeaders.Headers.Where(h => h.Key == "x-pagination").FirstOrDefault();
            var paginationParams = JsonConvert.DeserializeObject<PaginationParams>(headersParams.Value.FirstOrDefault());

            // 更新界面参数
            ShowOpLogsList = new ObservableCollection<OperationLogsDto>(resultWithHeaders.Data);
            IsShowPaginationAndDataGrid = ShowOpLogsList.Count() == 0 ? Visibility.Collapsed : Visibility.Visible;
            DataCountPerPage = paginationParams.PageSize;
            PageIndex = paginationParams.CurrentPage;
            MaxPageCount = paginationParams.TotalPages;
        }

        private async Task PageUpdated(FunctionEventArgs<int> curPageNum)
        {
            await RetrieveDataGridSource(UserName, From, End, curPageNum.Info, _dataCountPerPage);
        }

        private async Task RetrieveRequestBodyContent(OperationLogsDto seletedLog)
        {
            if (seletedLog == null) return;
            var result = await _operationLogService.GetRequestBodyByIdAsync(seletedLog.Id);
            hc.MessageBox.Show(FormatJsonString(result), "请求内容", MessageBoxButton.OK, MessageBoxImage.Information);
        }

        /// <summary>
        /// 格式化Json字符串,使其显示便于阅读
        /// </summary>
        /// <param name="str">符合Josn标准的字符串</param>
        /// <returns></returns>
        private string FormatJsonString(string str)
        {
            try
            {
                //格式化json字符串
                JsonSerializer serializer = new JsonSerializer();
                TextReader tr = new StringReader(str);
                JsonTextReader jtr = new JsonTextReader(tr);
                object obj = serializer.Deserialize(jtr);
                if (obj != null)
                {
                    StringWriter textWriter = new StringWriter();
                    JsonTextWriter jsonWriter = new JsonTextWriter(textWriter)
                    {
                        Formatting = Formatting.Indented,
                        Indentation = 4,
                        IndentChar = ' '
                    };
                    serializer.Serialize(jsonWriter, obj);
                    return textWriter.ToString();
                }

                return str;
            }
            catch (Exception e)
            {
                hc.MessageBox.Show(
                    "请求数据无法格式化!\n" +
                    $"异常信息:{e.Message}", 
                    "错误", 
                    MessageBoxButton.OK, 
                    MessageBoxImage.Error);
                return string.Empty;
            }
        }

        #endregion


        #region 接口的实现

        public async void OnNavigatedTo(NavigationContext navigationContext)
        {
            _showOpLogsList.Clear();

            await RetrieveDataGridSource(string.Empty, _from, DateTime.Today.AddHours(12), 1, _dataCountPerPage);
        }

        public bool IsNavigationTarget(NavigationContext navigationContext)
        {
            return true;
        }

        public void OnNavigatedFrom(NavigationContext navigationContext)
        {

        }

        #endregion
    }
}
